import * as Cesium from "cesium";

export default class GridCell {

  // 添加当前层索引指针
  currentLayerIndex = 0

  constructor(viewer, position, size = 15.0) {
    this.viewer = viewer;
    this.position = position;
    // 立方体大小
    this.halfSize = size / 2;
    // 方向枚举
    // 将[经度,纬度,高度]数组转换为Cartesian3对象
    const cartesian = Cesium.Cartesian3.fromDegrees(
      position[0],
      position[1],
      position[2]
    );
    // 创建一个局部坐标系的变换矩阵，防止因地球曲率导致的变形
    const hpr = new Cesium.HeadingPitchRoll(0, 0, 0);
    const orientation = Cesium.Transforms.headingPitchRollQuaternion(
      cartesian,
      hpr
    );
    this.modelMatrix = Cesium.Matrix4.fromTranslationQuaternionRotationScale(
      cartesian, // 平移
      orientation, // 旋转
      new Cesium.Cartesian3(1, 1, 1) // 缩放
    );

    // 重新计算逆矩阵
    this.inverseMatrix = Cesium.Matrix4.inverse(
      this.modelMatrix,
      new Cesium.Matrix4()
    );

    this.allColor = {
      // 异常
      Red: new Cesium.Color(1.0, 0.0, 0.0, 0.3),
      // 警告
      Yellow: new Cesium.Color(1.0, 1.0, 0.0, 0.3),
      // 计划
      Green: new Cesium.Color(0.0, 1.0, 0.0, 0.3),
      // 当前网格 - 自定义绿色高亮 RGB(50, 205, 50)
      DarkGreen: new Cesium.Color(34 / 255, 139 / 255, 34 / 255, 0.5),
      // 正常
      White: new Cesium.Color(1.0, 1.0, 1.0, 0.3),
    };

    // 启用场景抗锯齿
    this.viewer.scene.postProcessStages.fxaa.enabled = true;
    // 用于存储每个扩展层的顶点和颜色
    this.layers = [];
    // 初始化几何数据
    this.initGeometryData();

    // 存储创建的primitives - 直接定义为类属性而不是嵌套对象
    // 异常
    this.primitiveRed = null;
    // 警告
    this.primitiveYellow = null;
    // 计划
    this.primitiveGreen = null;
    // 当前网格 - 深绿色
    this.primitiveDarkGreen = null;
    // 正常
    this.primitiveWhite = null;
    // 边缘线
    this.edgePrimitive = null;
  }

  initGeometryData () {
    // 顶点坐标
    this.positions = new Float64Array([
      -this.halfSize,
      -this.halfSize,
      -this.halfSize, // 0
      this.halfSize,
      -this.halfSize,
      -this.halfSize, // 1
      this.halfSize,
      this.halfSize,
      -this.halfSize, // 2
      -this.halfSize,
      this.halfSize,
      -this.halfSize, // 3
      -this.halfSize,
      -this.halfSize,
      this.halfSize, // 4
      this.halfSize,
      -this.halfSize,
      this.halfSize, // 5
      this.halfSize,
      this.halfSize,
      this.halfSize, // 6
      -this.halfSize,
      this.halfSize,
      this.halfSize, // 7
    ]);
    // 索引
    this.indices = new Uint16Array([
      0,
      1,
      2,
      0,
      2,
      3, // 底面
      4,
      5,
      6,
      4,
      6,
      7, // 顶面
      0,
      1,
      5,
      0,
      5,
      4, // 前面
      1,
      2,
      6,
      1,
      6,
      5, // 右面
      2,
      3,
      7,
      2,
      7,
      6, // 后面
      3,
      0,
      4,
      3,
      4,
      7, // 左面
    ]);

    // 基础层(底部立方体)使用白色
    this.layers = [
      {
        positions: new Float64Array(this.positions),
        indices: new Uint16Array(this.indices),
        color: "White",
        keyIndex: [0, 0, 0],
      },
    ];
  }

  // 向上方添加一个立方体
  extend (direction, offset = 1, color) {
    console.log("extend->color->", color);
    // 获取当前基准层的立方体数据（使用指针而不是数组最后一个元素）
    const currentLayer = this.layers[this.currentLayerIndex];
    const lastPositions = currentLayer.positions;
    const lastKeyIndex = currentLayer.keyIndex || [0, 0, 0]; // 获取当前基准层的keyIndex
    // 计算偏移距离
    const distance = this.halfSize * 2 * offset;
    // 创建新的顶点数组
    const newPositions = new Float64Array(lastPositions.length);
    // 根据方向更新keyIndex
    let newKeyIndex = [...lastKeyIndex]; // 复制当前基准层的keyIndex
    // 根据方向更新keyIndex：第一个元素控制左右，第二个元素控制前后，第三个元素控制上下
    switch (direction) {
      case "1_0_0":
        newKeyIndex[0] = lastKeyIndex[0] + 1; // 向左时第一个元素+1
        break;
      case "-1_0_0":
        newKeyIndex[0] = lastKeyIndex[0] - 1; // 向右时第一个元素-1
        break;
      case "0_1_0":
        newKeyIndex[1] = lastKeyIndex[1] + 1; // 向前时第二个元素+1
        break;
      case "0_-1_0":
        newKeyIndex[1] = lastKeyIndex[1] - 1; // 向后时第二个元素-1
        break;
      case "0_0_1":
        newKeyIndex[2] = lastKeyIndex[2] + 1; // 向上时第三个元素+1
        break;
      case "0_0_-1":
        newKeyIndex[2] = lastKeyIndex[2] - 1; // 向下时第三个元素-1
        break;
    }

    // 检查是否已存在具有相同keyIndex的层
    const existingLayerIndex = this.layers.findIndex(
      (layer) =>
        layer.keyIndex &&
        layer.keyIndex[0] === newKeyIndex[0] &&
        layer.keyIndex[1] === newKeyIndex[1] &&
        layer.keyIndex[2] === newKeyIndex[2]
    );

    // 如果存在相同keyIndex的层，只更新颜色并更新当前指针
    if (existingLayerIndex !== -1) {
      console.log("已存在相同keyIndex的立方体，更新颜色");
      this.layers[existingLayerIndex].color = color;
      this.layers[existingLayerIndex].show = true;

      // 更新当前层指针到找到的层，这样下次extend就会基于这个层
      this.currentLayerIndex = existingLayerIndex;

      // 重新构建整体的几何数据
      this.rebuildGeometry();
      return this;
    }

    // 复制立方体的顶点并根据方向添加偏移
    for (let i = 0; i < lastPositions.length; i += 3) {
      newPositions[i] = lastPositions[i]; // 默认x不变
      newPositions[i + 1] = lastPositions[i + 1]; // 默认y不变
      newPositions[i + 2] = lastPositions[i + 2]; // 默认z不变
      // 根据不同方向调整坐标
      switch (direction.toLowerCase()) {
        case "1_0_0": // 向左
          newPositions[i] = lastPositions[i] - distance;
          break;
        case "-1_0_0": // 向右
          newPositions[i] = lastPositions[i] + distance;
          break;
        case "0_1_0": // 向前
          newPositions[i + 1] = lastPositions[i + 1] - distance;
          break;
        case "0_-1_0": // 向后
          newPositions[i + 1] = lastPositions[i + 1] + distance;
          break;
        case "0_0_1": // 向上
          newPositions[i + 2] = lastPositions[i + 2] + distance;
          break;
        case "0_0_-1": // 向下
          newPositions[i + 2] = lastPositions[i + 2] - distance;
          break;
        default:
          console.warn("无效的方向:", direction);
          return this;
      }
    }
    // 创建新的索引数组（与当前基准层相同）
    const newIndices = new Uint16Array(currentLayer.indices);
    // 计算新立方体的中心点坐标
    // 每个立方体有8个顶点，找到它们的平均值来计算中心点
    const center = [0, 0, 0];
    for (let i = 0; i < newPositions.length; i += 3) {
      center[0] += newPositions[i] / 8; // x坐标累加
      center[1] += newPositions[i + 1] / 8; // y坐标累加
      center[2] += newPositions[i + 2] / 8; // z坐标累加
    }
    // console.log('this.layers->', this.layers.length);
    // console.log('newKeyIndex->', newKeyIndex);
    // console.log('center->', center);

    // 计算中心点坐标
    const localCenter = new Cesium.Cartesian3(center[0], center[1], center[2]);
    const worldCenter = Cesium.Matrix4.multiplyByPoint(
      this.modelMatrix,
      localCenter,
      new Cesium.Cartesian3()
    );
    const cartographic = Cesium.Cartographic.fromCartesian(worldCenter);
    const centerLLA = [
      Cesium.Math.toDegrees(cartographic.longitude),
      Cesium.Math.toDegrees(cartographic.latitude),
      cartographic.height,
    ];

    // 添加新的层
    this.layers.push({
      positions: newPositions,
      indices: newIndices,
      color: color,
      show: true,
      keyIndex: newKeyIndex, // 添加更新后的keyIndex
      centerPoint: centerLLA, // 添加中心点坐标
    });

    // 更新当前层指针到新添加的层
    this.currentLayerIndex = this.layers.length - 1;

    // 重新构建整体的几何数据
    this.rebuildGeometry();
    return this;
  }

  // 重新构建几何数据
  rebuildGeometry () {
    // 计算总的顶点和索引数量
    let totalVertices = 0;
    let totalIndices = 0;

    this.layers.forEach((layer) => {
      totalVertices += layer.positions.length;
      totalIndices += layer.indices.length;
    });

    // 创建新的合并数组
    const newPositions = new Float64Array(totalVertices);
    const newIndices = new Uint16Array(totalIndices);

    let posOffset = 0;
    let idxOffset = 0;
    let vertexCount = 0;

    // 合并各层的几何数据
    this.layers.forEach((layer) => {
      // 复制顶点
      newPositions.set(layer.positions, posOffset);

      // 复制索引（需要调整索引值）
      for (let i = 0; i < layer.indices.length; i++) {
        newIndices[idxOffset + i] = layer.indices[i] + vertexCount;
      }

      posOffset += layer.positions.length;
      idxOffset += layer.indices.length;
      vertexCount += layer.positions.length / 3;
    });

    // 更新几何数据
    this.positions = newPositions;
    this.indices = newIndices;
  }

  // 销毁所有primitives
  destroy () {
    // 移除所有primitives
    if (this.primitiveRed && !this.primitiveRed.isDestroyed()) {
      this.viewer.scene.primitives.remove(this.primitiveRed);
    }
    if (this.primitiveYellow && !this.primitiveYellow.isDestroyed()) {
      this.viewer.scene.primitives.remove(this.primitiveYellow);
    }
    if (this.primitiveGreen && !this.primitiveGreen.isDestroyed()) {
      this.viewer.scene.primitives.remove(this.primitiveGreen);
    }
    if (this.primitiveDarkGreen && !this.primitiveDarkGreen.isDestroyed()) {
      this.viewer.scene.primitives.remove(this.primitiveDarkGreen);
    }
    if (this.primitiveWhite && !this.primitiveWhite.isDestroyed()) {
      this.viewer.scene.primitives.remove(this.primitiveWhite);
    }
    if (this.edgePrimitive && !this.edgePrimitive.isDestroyed()) {
      this.viewer.scene.primitives.remove(this.edgePrimitive);
    }

    // 重置primitives引用
    this.primitiveRed = null;
    this.primitiveYellow = null;
    this.primitiveGreen = null;
    this.primitiveDarkGreen = null;
    this.primitiveWhite = null;
    this.edgePrimitive = null;
  }

  // 重置GridCell，销毁所有primitives并重置几何数据
  reset (position) {
    // 销毁所有primitives
    this.destroy();

    // 重置layers数组
    this.layers = [];

    // 重置当前层指针
    this.currentLayerIndex = 0;

    // 如果传入position，重置中心坐标和矩阵
    if (position) {
      this.position = position;
      const cartesian = Cesium.Cartesian3.fromDegrees(
        position[0],
        position[1],
        position[2]
      );
      const hpr = new Cesium.HeadingPitchRoll(0, 0, 0);
      const orientation = Cesium.Transforms.headingPitchRollQuaternion(
        cartesian,
        hpr
      );
      this.modelMatrix = Cesium.Matrix4.fromTranslationQuaternionRotationScale(
        cartesian, // 平移
        orientation, // 旋转
        new Cesium.Cartesian3(1, 1, 1) // 缩放
      );

      // 重新计算逆矩阵
      this.inverseMatrix = Cesium.Matrix4.inverse(
        this.modelMatrix,
        new Cesium.Matrix4()
      );
    }

    // 重新初始化几何数据
    this.initGeometryData();

    console.log("GridCell已重置，所有primitives已销毁，几何数据已重新初始化");
    return this;
  }

  drawBox () {
    // console.log('drawBox->this.layers->', this.layers);
    // 按颜色分组整合数据
    const colorGroups = {
      Red: { positions: [], indices: [], vertexCount: 0 },
      Yellow: { positions: [], indices: [], vertexCount: 0 },
      Green: { positions: [], indices: [], vertexCount: 0 },
      DarkGreen: { positions: [], indices: [], vertexCount: 0 },
      White: { positions: [], indices: [], vertexCount: 0 },
    };
    // this.layers[this.layers.length - 1].color = 'Green'
    // 首先按颜色分配立方体
    this.layers.forEach((layer) => {
      // 检查该方格是否需要显示
      if (layer.show === false) {
        // 如果show为false，跳过该方格
        return;
      }

      const color = layer.color || "White";
      if (!colorGroups[color]) {
        console.warn(`未知颜色: ${color}, 将使用White`);
        layer.color = "White";
      }

      // 添加顶点到对应颜色组
      for (let i = 0; i < layer.positions.length; i++) {
        colorGroups[color].positions.push(layer.positions[i]);
      }

      // 添加索引到对应颜色组
      for (let i = 0; i < layer.indices.length; i++) {
        // 索引值需要根据当前颜色组已有的顶点数进行调整
        colorGroups[color].indices.push(
          layer.indices[i] + colorGroups[color].vertexCount
        );
      }

      // 更新该颜色组的顶点计数
      colorGroups[color].vertexCount += layer.positions.length / 3;
    });

    // 清除场景中的现有primitives
    this.destroy();

    // 为每种颜色创建primitive
    // 红色
    if (colorGroups.Red.positions.length > 0) {
      // console.log('Creating Red primitive with', colorGroups.Red.positions.length / 3, 'vertices');
      this.primitiveRed = this.createCubePrimitive(
        this.allColor.Red,
        new Uint16Array(colorGroups.Red.indices),
        new Float64Array(colorGroups.Red.positions)
      );
      this.viewer.scene.primitives.add(this.primitiveRed);
    }

    // 黄色
    if (colorGroups.Yellow.positions.length > 0) {
      // console.log('Creating Yellow primitive with', colorGroups.Yellow.positions.length / 3, 'vertices');
      this.primitiveYellow = this.createCubePrimitive(
        this.allColor.Yellow,
        new Uint16Array(colorGroups.Yellow.indices),
        new Float64Array(colorGroups.Yellow.positions)
      );
      this.viewer.scene.primitives.add(this.primitiveYellow);
    }

    // 绿色
    if (colorGroups.Green.positions.length > 0) {
      this.primitiveGreen = this.createCubePrimitive(
        this.allColor.Green,
        new Uint16Array(colorGroups.Green.indices),
        new Float64Array(colorGroups.Green.positions)
      );
      this.viewer.scene.primitives.add(this.primitiveGreen);
    }

    // 深绿色
    if (colorGroups.DarkGreen.positions.length > 0) {
      this.primitiveDarkGreen = this.createCubePrimitive(
        this.allColor.DarkGreen,
        new Uint16Array(colorGroups.DarkGreen.indices),
        new Float64Array(colorGroups.DarkGreen.positions)
      );
      this.viewer.scene.primitives.add(this.primitiveDarkGreen);
    }

    // 白色
    if (colorGroups.White.positions.length > 0) {
      this.primitiveWhite = this.createCubePrimitive(
        this.allColor.White,
        new Uint16Array(colorGroups.White.indices),
        new Float64Array(colorGroups.White.positions)
      );
      this.viewer.scene.primitives.add(this.primitiveWhite);
    }

    // 处理边缘线
    if (this.edgePrimitive && !this.edgePrimitive.isDestroyed()) {
      // 删除旧的边缘线并创建新的
      this.viewer.scene.primitives.remove(this.edgePrimitive);
      this.edgePrimitive = this.createEdgesPrimitive();
      this.viewer.scene.primitives.add(this.edgePrimitive);
    } else {
      // 创建新的边缘线primitive
      this.edgePrimitive = this.createEdgesPrimitive();
      // 添加到场景中
      this.viewer.scene.primitives.add(this.edgePrimitive);
    }
    return {
      primitiveRed: this.primitiveRed,
      primitiveYellow: this.primitiveYellow,
      primitiveGreen: this.primitiveGreen,
      primitiveDarkGreen: this.primitiveDarkGreen,
      primitiveWhite: this.primitiveWhite,
      edgePrimitive: this.edgePrimitive,
    };
  }

  // 创建立方体边缘线
  createEdgesPrimitive () {
    // 计算所有立方体的边缘线索引
    let edgeIndices = [];

    // 为每一层立方体生成边缘线索引
    let vertexOffset = 0;

    this.layers.forEach((layer) => {
      const vertexCount = layer.positions.length / 3;
      // 此层立方体的12条边的索引
      const layerEdgeIndices = [
        // 底面四条边
        vertexOffset + 0,
        vertexOffset + 1,
        vertexOffset + 1,
        vertexOffset + 2,
        vertexOffset + 2,
        vertexOffset + 3,
        vertexOffset + 3,
        vertexOffset + 0,
        // 顶面四条边
        vertexOffset + 4,
        vertexOffset + 5,
        vertexOffset + 5,
        vertexOffset + 6,
        vertexOffset + 6,
        vertexOffset + 7,
        vertexOffset + 7,
        vertexOffset + 4,
        // 连接顶面和底面的四条边
        vertexOffset + 0,
        vertexOffset + 4,
        vertexOffset + 1,
        vertexOffset + 5,
        vertexOffset + 2,
        vertexOffset + 6,
        vertexOffset + 3,
        vertexOffset + 7,
      ];

      // 将此层的边缘线索引添加到总索引数组
      edgeIndices = edgeIndices.concat(layerEdgeIndices);

      // 更新顶点偏移量
      vertexOffset += vertexCount;
    });

    // 准备边线的颜色 - 根据每个立方体的颜色设置边缘线颜色
    const edgeColorValues = new Uint8Array((this.positions.length / 3) * 4);

    // 重新遍历layers来设置每个顶点的颜色
    let currentVertexIndex = 0;
    this.layers.forEach((layer, layerIndex) => {
      // 检查该方格是否需要显示
      if (layer.show === false) {
        // 如果show为false，跳过该方格的颜色设置
        currentVertexIndex += layer.positions.length / 3;
        return;
      }

      const layerColor = layer.color || 'White';

      // 确保颜色名称正确匹配allColor中的键
      let cesiumColor;
      if (this.allColor[layerColor]) {
        cesiumColor = this.allColor[layerColor];
      } else {
        console.warn(`未找到颜色 ${layerColor}，使用默认白色`);
        cesiumColor = this.allColor.White;
      }

      // 直接使用allColor中定义的颜色，将Cesium颜色转换为RGB值（0-255范围）
      const r = Math.floor(cesiumColor.red * 255);
      const g = Math.floor(cesiumColor.green * 255);
      const b = Math.floor(cesiumColor.blue * 255);
      // 边缘线使用完全不透明以确保可见性
      const a = 255;

      // 为该层的所有顶点设置颜色
      const vertexCount = layer.positions.length / 3;
      for (let i = 0; i < vertexCount; i++) {
        const colorIndex = (currentVertexIndex + i) * 4;
        edgeColorValues[colorIndex] = r;     // R
        edgeColorValues[colorIndex + 1] = g; // G
        edgeColorValues[colorIndex + 2] = b; // B
        edgeColorValues[colorIndex + 3] = a; // A
      }

      currentVertexIndex += vertexCount;
    });

    return new Cesium.Primitive({
      geometryInstances: new Cesium.GeometryInstance({
        geometry: new Cesium.Geometry({
          attributes: {
            position: new Cesium.GeometryAttribute({
              componentDatatype: Cesium.ComponentDatatype.DOUBLE,
              componentsPerAttribute: 3,
              values: this.positions,
            }),
            color: new Cesium.GeometryAttribute({
              componentDatatype: Cesium.ComponentDatatype.UNSIGNED_BYTE,
              componentsPerAttribute: 4,
              values: edgeColorValues,
              normalize: true,
            }),
          },
          indices: new Uint16Array(edgeIndices),
          primitiveType: Cesium.PrimitiveType.LINES,
          boundingSphere: Cesium.BoundingSphere.fromVertices(this.positions),
          vertexFormat: Cesium.VertexFormat.POSITION_AND_COLOR,
        }),
        modelMatrix: this.modelMatrix,
      }),
      appearance: new Cesium.PerInstanceColorAppearance({
        flat: true,
        translucent: false,
        vertexFormat: Cesium.VertexFormat.POSITION_AND_COLOR,
        renderState: {
          lineWidth: Math.min(2.0, this.viewer.scene.maximumAliasedLineWidth),
          depthTest: {
            enabled: true,
          },
          depthMask: true,
        },
      }),
      asynchronous: false,
      releaseGeometryInstances: false,
      allowPicking: false,
    });
  }

  // 创建多个立方体
  createCubePrimitive (color, indicesArr, positionsArr) {
    // 使用传入的颜色或默认颜色
    const instanceColor = color || new Cesium.Color(1.0, 1.0, 1.0, 0.2);
    const oneIndices = indicesArr || this.indices;
    const onePositions = positionsArr || this.positions;

    // 创建可更新的 Primitive
    return new Cesium.Primitive({
      geometryInstances: new Cesium.GeometryInstance({
        geometry: new Cesium.Geometry({
          attributes: {
            position: new Cesium.GeometryAttribute({
              componentDatatype: Cesium.ComponentDatatype.DOUBLE,
              componentsPerAttribute: 3,
              values: onePositions,
            }),
          },
          indices: oneIndices,
          primitiveType: Cesium.PrimitiveType.TRIANGLES,
          boundingSphere: Cesium.BoundingSphere.fromVertices(onePositions),
          vertexFormat: Cesium.VertexFormat.ALL,
        }),
        attributes: {
          color: Cesium.ColorGeometryInstanceAttribute.fromColor(instanceColor),
        },
        modelMatrix: this.modelMatrix,
      }),
      appearance: new Cesium.PerInstanceColorAppearance({
        flat: true,
        translucent: true,
        vertexFormat: Cesium.VertexFormat.ALL,
      }),
      asynchronous: false,
      releaseGeometryInstances: false,
      updatersPerAttribute: 1,
      // 启用抗锯齿功能
      renderState: {
        depthTest: {
          enabled: true,
        },
        depthMask: false,
        blending: Cesium.BlendingState.ALPHA_BLEND,
        // 启用多重采样抗锯齿
        framebuffer: {
          msaa: true,
        },
      },
    });
  }

  /**
   * 根据MQTT传入的经纬度点位计算与中心点的偏移量
   * @param {Array} mqttPosition - MQTT传入的经纬度点位 [longitude, latitude, height]
   * @returns {Array} - 返回一个三元素数组 [左右偏移量,前后偏移量,上下偏移量]
   * 正数表示向左、向前、向上的偏移，负数表示向右、向后、向下的偏移
   */
  getKeyIndexByLLA (mqttPosition) {
    // 将目标点转换为Cartesian3坐标
    const targetCartesian = Cesium.Cartesian3.fromDegrees(
      mqttPosition[0],
      mqttPosition[1],
      mqttPosition[2] || 0
    );

    // 计算目标点在模型局部坐标系中的位置
    const localPosition = Cesium.Matrix4.multiplyByPoint(
      this.inverseMatrix,
      targetCartesian,
      new Cesium.Cartesian3()
    );

    // 计算网格单元尺寸
    const gridUnitSize = this.halfSize * 2;

    // 计算网格偏移量（注意坐标系方向）
    const leftRightOffset = Math.round(-localPosition.x / gridUnitSize);
    const frontBackOffset = Math.round(-localPosition.y / gridUnitSize);
    const upDownOffset = Math.round(localPosition.z / gridUnitSize);
    return [leftRightOffset, frontBackOffset, upDownOffset];
  }

  /**
   * 根据偏移量数组添加立方体
   * @param {Array} offsetsArray - 偏移量数组 [左右偏移量,前后偏移量,上下偏移量]
   * @param {String} color - 立方体颜色，如'Red', 'Yellow', 'Green', 'White'
   * @returns {GridCell} - 返回GridCell实例自身，用于链式调用
   */
  extendByOffsets (offsetsArray, color) {
    if (!Array.isArray(offsetsArray) || offsetsArray.length !== 3) {
      console.error(
        "偏移量数组格式不正确，应为[左右偏移量,前后偏移量,上下偏移量]"
      );
      return this;
    }

    // 遍历三个方向的偏移量
    offsetsArray.forEach((offset, index) => {
      if (offset === 0) return; // 如果偏移量为0，跳过此方向

      // 创建方向字符串，例如 '1_0_0', '0_1_0', '0_0_1'
      let direction = [0, 0, 0];
      direction[index] = offset > 0 ? 1 : -1; // 根据偏移量正负设置方向
      const directionString = direction.join("_");

      // 根据偏移量的绝对值添加多个立方体
      const absOffset = Math.abs(offset);
      for (let i = 0; i < absOffset; i++) {
        this.extend(directionString, 1, color);
      }
    });

    return this;
  }

  /**
  * 改变方格的颜色
  * @param {Object} options - 配置对象
  * @param {Array} options.position - 经纬度数组 [longitude, latitude, height]
  * @param {String} options.color - 立方体颜色，如'Red', 'Yellow', 'Green', 'White'
  * @param {Boolean} options.isGridColor - 是否使用网格颜色，为true时使用DarkGreen
  * @param {Number} options.mode - 模式，0为默认模式，1为批量更新模式
  * @returns {GridCell} - 返回GridCell实例自身，用于链式调用
  */
  changeColor (options = {}) {
    // 解构参数，设置默认值
    const {
      position,
      color,
      isGridColor = false,
      mode = 0
    } = options;

    // 1. 参数验证
    if (!Array.isArray(position) || position.length < 2) {
      console.error("位置参数格式不正确，应为[经度,纬度,高度]");
      return this;
    }

    if (!color || !this.allColor[color]) {
      console.error("无效的颜色值，应为'Red', 'Yellow', 'Green', 'DarkGreen'或'White'");
      return this;
    }

    // 2. 坐标转换 - 将经纬度转换为局部坐标系
    const height = position.length > 2 ? position[2] : 0;
    const posCartesian = Cesium.Cartesian3.fromDegrees(
      position[0],
      position[1],
      height
    );

    // 计算逆矩阵和局部坐标
    const localPoint = Cesium.Matrix4.multiplyByPoint(
      this.inverseMatrix,
      posCartesian,
      new Cesium.Cartesian3()
    );

    // 3. 精确空间位置匹配 - 遍历所有立方体，找到包含目标点的立方体
    let targetLayer = null;

    for (const layer of this.layers) {
      if (!layer.keyIndex) continue;

      // 使用精确空间位置判断（包含边界值）
      if (this.isPointInCube(localPoint, layer)) {
        targetLayer = layer;
        break; // 找到精确匹配，立即退出循环
      } else {
        // mode为1时，检查每一个元素的颜色是不是 传入的color,如果不是则改变，是则不做任何处理
        if (mode && layer.color !== color) {
          layer.color = color;
        }
      }
    }
    // 4. 更新找到的立方体颜色
    if (targetLayer) {
      // 根据isGridColor参数决定使用的颜色
      const finalColor = isGridColor ? 'DarkGreen' : color;

      if (targetLayer.color !== finalColor || targetLayer.show === false) {
        targetLayer.color = finalColor;
        targetLayer.show = true;
        // console.log(`精确匹配: 已将坐标 [${position}] 对应的方格颜色更新为 ${finalColor}`);
        // 重建几何数据并重新绘制
        this.rebuildGeometry();
        this.drawBox();
      }
    } else {
      console.warn(`精确匹配失败: 未找到坐标 [${position}] 对应的方格`);
    }
    return this;
  }

  /**
   * 加载网格数据json，绘制整个网格
   * @param {Array} jsonData - 网格数据数组，每个元素包含经纬度坐标 [longitude, latitude, height]
   * @param {String} color - 立方体颜色，如'Red', 'Yellow', 'Green', 'White'
   * @param {Boolean} fillGaps - 是否填充空隙，true为补全模式，false为不补全模式，默认true
   * @returns {GridCell} - 返回GridCell实例自身，用于链式调用
   */
  loadGridDataJson (jsonData, color = 'White', fillGaps = true) {

    // 参数验证
    if (!Array.isArray(jsonData) || jsonData.length === 0) {
      console.warn('网格数据为空或格式不正确');
      return this;
    }

    // 验证颜色参数
    if (!this.allColor[color]) {
      console.warn(`无效的颜色值: ${color}，将使用默认颜色White`);
      color = 'White';
    }

    // 如果已有图层，重置到第一个点位作为新的中心点
    if (this.layers.length > 0) {
      // 重置到第一个点位作为新的中心点
      this.reset(jsonData[0]);
    }

    const optimizedData = jsonData;

    if (fillGaps) {
      // 补全模式：原有逻辑
      // 遍历所有点位数据
      for (let i = 0; i < optimizedData.length; i++) {
        const pointData = optimizedData[i];

        // 验证点位数据格式
        if (!Array.isArray(pointData) || pointData.length < 2) {
          console.warn(`跳过无效的点位数据: ${pointData}`);
          continue;
        }

        // 确保有高度值，如果没有则使用0
        const position = [
          pointData[0], // longitude
          pointData[1], // latitude
          pointData.length > 2 ? pointData[2] : 0 // height
        ];

        // 第一个点位作为中心点，不需要计算偏移
        if (i === 0) {
          // 基础层已经在reset或初始化时创建，只需要设置颜色
          if (this.layers.length > 0) {
            this.layers[0].color = color;
          }
          continue;
        }

        // 使用当前基准层的keyIndex作为上一个位置的网格索引
        // 避免重复计算上一个位置的网格索引
        const diffIndexXYZ1 = this.layers[this.currentLayerIndex].keyIndex;
        const diffIndexXYZ2 = this.getKeyIndexByLLA(position);

        const offsets = [
          diffIndexXYZ2[0] - diffIndexXYZ1[0], // x偏移
          diffIndexXYZ2[1] - diffIndexXYZ1[1], // y偏移
          diffIndexXYZ2[2] - diffIndexXYZ1[2], // z偏移
        ];

        // 根据偏移量添加立方体
        this.extendByOffsets(offsets, color);
      }
    } else {
      // 不补全模式：直接在指定位置创建立方体
      for (let i = 0; i < optimizedData.length; i++) {
        const pointData = optimizedData[i];

        // 验证点位数据格式
        if (!Array.isArray(pointData) || pointData.length < 2) {
          console.warn(`跳过无效的点位数据: ${pointData}`);
          continue;
        }

        // 确保有高度值，如果没有则使用0
        const position = [
          pointData[0], // longitude
          pointData[1], // latitude
          pointData.length > 2 ? pointData[2] : 0 // height
        ];

        // 第一个点位作为中心点
        if (i === 0) {
          // 基础层已经在reset或初始化时创建，只需要设置颜色
          if (this.layers.length > 0) {
            this.layers[0].color = color;
          }
          continue;
        }

        // 直接在指定位置创建立方体，不进行补全
        this.createCubeAtPosition(position, color);
      }
    }

    // 重建几何数据并绘制
    this.rebuildGeometry();
    this.drawBox();

    console.log(`网格数据加载完成，共创建 ${this.layers.length} 个立方体，${fillGaps ? '补全模式' : '不补全模式'}`);
    return this;
  }

  /**
   * 绘制单个方格
   * @param {Array} position - 经纬度数组 [longitude, latitude, height]
   * @param {String} color - 立方体颜色，如'Red', 'Yellow', 'Green', 'DarkGreen', 'White'
   * @returns {GridCell} - 返回GridCell实例自身，用于链式调用
   */
  drawSingleBox (position, color = 'White', index = 0) {
    // 参数验证
    if (!Array.isArray(position) || position.length < 2) {
      console.error("位置参数格式不正确，应为[经度,纬度,高度]");
      return this;
    }

    // 验证颜色参数
    if (!this.allColor[color]) {
      console.warn(`无效的颜色值: ${color}，将使用默认颜色White`);
      color = 'White';
    }

    // 确保有高度值，如果没有则使用0
    const normalizedPosition = [
      position[0], // longitude
      position[1], // latitude
      position.length > 2 ? position[2] : 0 // height
    ];

    // 如果没有图层，先创建基础图层
    if (this.layers.length === 0) {
      console.warn("没有基础图层，请先初始化GridCell或加载网格数据");
      return this;
    }

    // 直接从 this.layers 数组中获取第一个网格
    const firstLayer = this.layers[0];
    if (firstLayer && firstLayer.color === 'White') {
      firstLayer.color = color;
    }

    // 计算当前基准层的keyIndex和目标位置的keyIndex
    const currentKeyIndex = this.layers[this.currentLayerIndex].keyIndex;
    const targetKeyIndex = this.getKeyIndexByLLA(normalizedPosition);

    // 计算偏移量
    const xOffset = targetKeyIndex[0] - currentKeyIndex[0]; // 左右方向偏移
    const yOffset = targetKeyIndex[1] - currentKeyIndex[1]; // 前后方向偏移
    const zOffset = targetKeyIndex[2] - currentKeyIndex[2]; // 上下方向偏移

    // console.log(index, [xOffset, yOffset, zOffset], 'drawSingleBox');


    // 根据偏移量添加立方体
    this.extendByOffsets([xOffset, yOffset, zOffset], color);

    // 重建几何数据并绘制
    this.rebuildGeometry();
    this.drawBox();

    console.log(`已绘制单个方格，位置: [${normalizedPosition}]，颜色: ${color}`);
    return this;
  }

  /**
   * 判断一个点是否在立方体内部（优化版本）
   * @param {Cesium.Cartesian3} localPoint - 目标点在局部坐标系中的坐标（预计算）
   * @param {Object} layer - 立方体图层对象
   * @returns {Boolean} - 点是否在立方体内
   */
  isPointInCube (localPoint, layer) {
    // 获取立方体的大小
    const cubeSize = this.halfSize * 2;

    // 根据keyIndex计算立方体中心在局部坐标系中的位置
    const cubeCenter = new Cesium.Cartesian3(
      -layer.keyIndex[0] * cubeSize,  // 注意坐标系方向与keyIndex的关系
      -layer.keyIndex[1] * cubeSize,
      layer.keyIndex[2] * cubeSize
    );

    // 计算立方体的边界范围
    const minX = cubeCenter.x - this.halfSize;
    const maxX = cubeCenter.x + this.halfSize;
    const minY = cubeCenter.y - this.halfSize;
    const maxY = cubeCenter.y + this.halfSize;
    const minZ = cubeCenter.z - this.halfSize;
    const maxZ = cubeCenter.z + this.halfSize;

    // 判断点是否在立方体内（包括边界）
    const isInside =
      localPoint.x >= minX && localPoint.x <= maxX &&
      localPoint.y >= minY && localPoint.y <= maxY &&
      localPoint.z >= minZ && localPoint.z <= maxZ;

    return isInside;
  }

  /**
   * 在指定位置直接创建立方体（不补全中间的空隙）
   * @param {Array} position - 经纬度数组 [longitude, latitude, height]
   * @param {String} color - 立方体颜色，如'Red', 'Yellow', 'Green', 'DarkGreen', 'White'
   * @returns {GridCell} - 返回GridCell实例自身，用于链式调用
   */
  createCubeAtPosition (position, color = 'White') {
    // 参数验证
    if (!Array.isArray(position) || position.length < 2) {
      console.error("位置参数格式不正确，应为[经度,纬度,高度]");
      return this;
    }

    // 验证颜色参数
    if (!this.allColor[color]) {
      console.warn(`无效的颜色值: ${color}，将使用默认颜色White`);
      color = 'White';
    }

    // 确保有高度值，如果没有则使用0
    const normalizedPosition = [
      position[0], // longitude
      position[1], // latitude
      position.length > 2 ? position[2] : 0 // height
    ];

    // 计算目标位置的keyIndex
    const targetKeyIndex = this.getKeyIndexByLLA(normalizedPosition);

    // 检查是否已存在具有相同keyIndex的层
    const existingLayerIndex = this.layers.findIndex(
      (layer) =>
        layer.keyIndex &&
        layer.keyIndex[0] === targetKeyIndex[0] &&
        layer.keyIndex[1] === targetKeyIndex[1] &&
        layer.keyIndex[2] === targetKeyIndex[2]
    );

    // 如果存在相同keyIndex的层，只更新颜色
    if (existingLayerIndex !== -1) {
      console.log("已存在相同keyIndex的立方体，更新颜色");
      this.layers[existingLayerIndex].color = color;
      this.layers[existingLayerIndex].show = true;
      return this;
    }

    // 计算新立方体的顶点位置
    const gridUnitSize = this.halfSize * 2;
    const newPositions = new Float64Array(this.positions.length);

    // 根据keyIndex计算立方体中心在局部坐标系中的位置
    const cubeCenter = new Cesium.Cartesian3(
      -targetKeyIndex[0] * gridUnitSize,  // 注意坐标系方向
      -targetKeyIndex[1] * gridUnitSize,
      targetKeyIndex[2] * gridUnitSize
    );

    // 生成新立方体的8个顶点坐标
    for (let i = 0; i < this.positions.length; i += 3) {
      // 获取基础立方体的相对位置
      const relativeX = this.positions[i];
      const relativeY = this.positions[i + 1];
      const relativeZ = this.positions[i + 2];

      // 将相对位置加上立方体中心位置
      newPositions[i] = cubeCenter.x + relativeX;
      newPositions[i + 1] = cubeCenter.y + relativeY;
      newPositions[i + 2] = cubeCenter.z + relativeZ;
    }

    // 创建新的索引数组（与基础立方体相同）
    const newIndices = new Uint16Array(this.indices);

    // 计算新立方体的中心点世界坐标
    const worldCenter = Cesium.Matrix4.multiplyByPoint(
      this.modelMatrix,
      cubeCenter,
      new Cesium.Cartesian3()
    );
    const cartographic = Cesium.Cartographic.fromCartesian(worldCenter);
    const centerLLA = [
      Cesium.Math.toDegrees(cartographic.longitude),
      Cesium.Math.toDegrees(cartographic.latitude),
      cartographic.height,
    ];

    // 添加新的层
    this.layers.push({
      positions: newPositions,
      indices: newIndices,
      color: color,
      show: true,
      keyIndex: targetKeyIndex,
      centerPoint: centerLLA,
    });

    console.log(`在位置 [${normalizedPosition}] 创建立方体，keyIndex: [${targetKeyIndex}]，颜色: ${color}`);
    return this;
  }
}
